package org.jeecg.modules.engineering.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.netflix.discovery.converters.jackson.EurekaXmlJacksonCodec;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.*;
import org.jeecg.modules.engineering.entity.EquipCollectRelation;
import org.jeecg.modules.engineering.entity.EquipEventSortDetail;
import org.jeecg.modules.engineering.entity.EquipInfo;
import org.jeecg.modules.engineering.mapper.EquipCollectRelationMapper;
import org.jeecg.modules.engineering.mapper.EquipInfoMapper;
import org.jeecg.modules.engineering.service.IEquipInfoService;
import org.jeecg.modules.engineering.service.IEquipLinkThingService;
import org.jeecg.modules.engineering.vo.CollectDataApiParam;
import org.jeecg.modules.engineering.vo.EquipEventInfoProcess;
import org.jeecg.modules.engineering.vo.EquipStatusReport;
import org.jeecg.modules.engineering.vo.LinkThingDeviceKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Description: 设备基础信息表
 * @Author: jeecg-boot
 * @Date:   2019-08-15
 * @Version: V1.0
 */
@Slf4j
@Service
public class EquipInfoServiceImpl extends ServiceImpl<EquipInfoMapper, EquipInfo> implements IEquipInfoService {


    @Autowired
    private EquipInfoMapper equipInfoMapper;

    @Autowired
    private EquipCollectRelationMapper equipCollectRelationMapper;

    @Autowired
    private IEquipLinkThingService equipLinkThingService;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public List<EquipStatusReport> findStatusByProjectAndSort(String projectId, String sortId) {
        return equipInfoMapper.findStatusByProjectAndSort(projectId,sortId);
    }

    @Override
    @Transactional
    public void saveEquip(EquipInfo equipInfo) {
        try{
            //添加设备到物管中心
            Map<String, String> maps = equipLinkThingService.addEquip(equipInfo.getEquipCode());
            if(maps != null){
                String signKey = maps.get(equipInfo.getEquipCode());
                if(signKey != null){
                    equipInfo.setSignKey(signKey);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("设备添加到物管中心出现异常"+e);
        }

        boolean result = save(equipInfo);
        if(equipInfo.getCollectList() != null && equipInfo.getCollectList().size() > 0){
            equipCollectRelationMapper.insertBatch(getRelations(equipInfo));
        }

        if(result){
            //以ID为key，存储到redis
            setToRedis(equipInfo);
        }

        try{
            //同步设备信息到物管中心
            equipLinkThingService.syncEquipInfo(Collections.singletonList(equipInfo));
        }catch (Exception e){
            e.printStackTrace();
            log.error("数据同步到物管中心出现异常"+e);
        }

    }

    @Override
    @Transactional
    public boolean updateEquip(EquipInfo equipInfo) {
        EquipInfo oldEntity = getById(equipInfo.getId());
        boolean result = updateById(equipInfo);
        deleteRelation(equipInfo);

        if(equipInfo.getCollectList() != null && equipInfo.getCollectList().size() > 0){
            equipCollectRelationMapper.insertBatch(getRelations(equipInfo));
        }
        if(result){
            //先移除编辑前的redis键值
            removeFromRedis(oldEntity);
            //更新成功后，重新设置redis
            setToRedis(equipInfo);
        }
        try {
            //同步设备信息到物管中心
            equipLinkThingService.syncEquipInfo(Collections.singletonList(equipInfo));
        }catch (Exception e){
            e.printStackTrace();
            log.error("数据同步到物管中心异常"+e);
        }

        return result;
    }

    private void deleteRelation(EquipInfo equipInfo) {
        //逻辑删除原来的数据
        Map<String, Object> params = new HashMap<>();
        params.put("id", equipInfo.getId());
        params.put("updateBy", SsoUtil.getLoginUser() == null ? "" : SsoUtil.getLoginUser().getUsername());
        params.put("updateTime", new Date());
        equipCollectRelationMapper.deleteByEquipId(params);
    }

    @Override
    public void removeWithRedis(String id) {
        EquipInfo entity = getById(id);
        //从数据库删除
        boolean result = removeById(id);
        //逻辑删除原来的数据
        deleteRelation(entity);
        if(result){
            //从redis删除
            removeFromRedis(entity);
        }
    }

    @Override
    public List<EquipInfo> getEquipInfoByCollectorId(String id) {
        return equipInfoMapper.getEquipInfoByCollectorId(id);
    }

    @Override
    public List<EquipStatusReport> findStatusByProjectAndSystem(String projectId, String topSystem) {
        return equipInfoMapper.findStatusByProjectAndSystem(projectId,topSystem);
    }

    @Override
    public List<EquipEventInfoProcess> findProcessByProjectAndDate(String projectId, String topSystem, Date month) {
        return equipInfoMapper.findProcessByProjectAndDate(projectId,topSystem,month);
    }

    private List<EquipCollectRelation> getRelations(EquipInfo equipInfo){
        List<EquipCollectRelation> relations = new ArrayList<>();
        for (String collect : equipInfo.getCollectList()){
            EquipCollectRelation relation = new EquipCollectRelation();
            relation.setEquipId(equipInfo.getId());
            relation.setItemId(collect);
            relation.setCreateTime(new Date());
            LoginUser sysUser = SsoUtil.getLoginUser();
            relation.setCreateBy(sysUser == null ? "" : sysUser.getUsername());
            relation.setTenantId(equipInfo.getTenantId());
            relations.add(relation);
        }
        return relations;
    }

    @Override
    public void setToRedis(EquipInfo entity){
        if(entity == null){
            return;
        }
        redisUtil.set(CacheConstant.REDIS_TABLES+"equip_info:id:"+entity.getId(), JSONObject.toJSONString(entity));
        redisUtil.set(CacheConstant.REDIS_TABLES+"equip_info:otherKey:equip_code:"+entity.getEquipCode(),entity.getId());
        redisUtil.set(CacheConstant.REDIS_TABLES+"equip_info:otherKey:equip_out_code:"+entity.getEquipOutCode(),entity.getId());
    }

    @Override
    public void removeFromRedis(String id){
        removeFromRedis(findById(id));
    }

    @Override
    public void removeFromRedis(EquipInfo entity){
        if(entity == null){
            return;
        }
        redisUtil.del(CacheConstant.REDIS_TABLES+"equip_info:id:"+entity.getId()
                ,CacheConstant.REDIS_TABLES+"equip_info:otherKey:equip_code:"+entity.getEquipCode()
                ,CacheConstant.REDIS_TABLES+"equip_info:otherKey:equip_out_code:"+entity.getEquipOutCode()
        );
    }

    @Override
    public EquipInfo getFromRedisByOtherKey(String key){
        String id = (String) redisUtil.get(CacheConstant.REDIS_TABLES+"equip_info:otherKey:"+key);
        if(StringUtils.isEmpty(id)){
            return null;
        }
        return getFromRedisById(id);
    }

    @Override
    public EquipInfo getFromRedisById(String id){
        EquipInfo entity = JSONObject.parseObject((String) redisUtil.get(CacheConstant.REDIS_TABLES+"equip_info:id:"+id),EquipInfo.class) ;
        if(entity == null){
            //从数据库查询
            entity = findById(id);
            if(entity != null){
                //重新设置redis
                setToRedis(entity);
            }
        }
        return entity;
    }

    @Override
    public List<CollectDataApiParam> getcollectParam(String id) {
        return equipInfoMapper.collectData(id);
    }

    private EquipInfo findById(String id) {
        return equipInfoMapper.findById(id);
    }

    @Override
    public Result<String> refreshToRedis() {
        List<EquipInfo> lists = list();
        if(lists != null && lists.size() > 0){
            for (EquipInfo entity : lists){
                setToRedis(entity);
            }
        }
        return Result.ok();
    }

    @Override
    public List<EquipInfo> findByProjectAndSystem(String departId, String projectId, String topSystem) {
        return equipInfoMapper.findByProjectAndSystem(departId,projectId,topSystem);
    }

    @Override
    public boolean checkHaveBySortIds(List<String> ids) {
        long count = equipInfoMapper.selectCountBySortIds(ids,ids.size());
        return count > 0;
    }

    @Override
    @Transactional
    public void batchRemoveWithRedis(List<String> ids) {
        if(ids != null && ids.size() > 0){
            for (String id :ids){
                removeWithRedis(id);
            }
        }
    }

    @Override
    public IPage<EquipInfo> selectSqlList(Page<EquipInfo> page, EquipInfo equipInfo, List<String> projectIds) {
        return page.setRecords(equipInfoMapper.selectSqlList(page,equipInfo,projectIds));
    }

    @Override
    public List<EquipInfo> selectSqlList(EquipInfo equipInfo, List<String> projectIds) {
        return equipInfoMapper.selectSqlList(null,equipInfo,projectIds);
    }

}
